
package com.joolun.cloud.mall.admin.controller;

import com.alipay.easysdk.payment.common.models.AlipayTradeFastpayRefundQueryResponse;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.joolun.cloud.common.core.constant.SecurityConstants;
import com.joolun.cloud.common.core.util.R;
import com.joolun.cloud.common.data.tenant.TenantContextHolder;
import com.joolun.cloud.common.log.annotation.SysLog;
import com.joolun.cloud.mall.admin.service.OrderInfoService;
import com.joolun.cloud.mall.admin.service.OrderItemService;
import com.joolun.cloud.mall.admin.service.ShopInfoService;
import com.joolun.cloud.mall.common.constant.MallConstants;
import com.joolun.cloud.mall.common.entity.OrderInfo;
import com.joolun.cloud.mall.common.entity.OrderItem;
import com.joolun.cloud.mall.common.entity.OrderRefunds;
import com.joolun.cloud.mall.admin.service.OrderRefundsService;
import com.joolun.cloud.mall.common.entity.ShopInfo;
import com.joolun.cloud.mall.common.enums.OrderRefundsEnum;
import com.joolun.cloud.mall.common.feign.FeignJooLunPayService;
import com.joolun.cloud.pay.common.constant.PayConstants;
import com.joolun.cloud.pay.common.dto.AliBaseRequest;
import com.joolun.cloud.pay.common.entity.PayConfig;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.annotations.Api;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * 退款详情
 *
 * @author www.joolun.com
 * @date 2019-11-14 16:35:25
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/orderrefunds")
@Api(value = "orderrefunds", tags = "退款详情管理")
public class OrderRefundsController {

    private final OrderRefundsService orderRefundsService;
	private final FeignJooLunPayService feignJooLunPayService;
	private final OrderInfoService orderInfoService;
	private final OrderItemService orderItemService;
	private final ShopInfoService shopInfoService;

    /**
     * 分页查询
     * @param page 分页对象
     * @param orderRefunds 退款详情
     * @return
     */
	@ApiOperation(value = "分页查询")
    @GetMapping("/page")
    @PreAuthorize("@ato.hasAuthority('mall:orderrefunds:index')")
    public R getOrderRefundsPage(Page page, OrderRefunds orderRefunds) {
        return R.ok(orderRefundsService.page1(page, orderRefunds));
    }

    /**
     * 通过id查询退款详情
     * @param id
     * @return R
     */
	@ApiOperation(value = "通过id查询退款详情")
    @GetMapping("/{id}")
    @PreAuthorize("@ato.hasAuthority('mall:orderrefunds:get')")
    public R getById(@PathVariable("id") String id) {
        return R.ok(orderRefundsService.getById(id));
    }

    /**
     * 新增退款详情
     * @param orderRefunds 退款详情
     * @return R
     */
	@ApiOperation(value = "新增退款详情")
    @SysLog("新增退款详情")
    @PostMapping
    @PreAuthorize("@ato.hasAuthority('mall:orderrefunds:add')")
    public R save(@RequestBody OrderRefunds orderRefunds) {
        return R.ok(orderRefundsService.save(orderRefunds));
    }

    /**
     * 修改退款详情
     * @param orderRefunds 退款详情
     * @return R
     */
	@ApiOperation(value = "修改退款详情")
    @SysLog("修改退款详情")
    @PutMapping
    @PreAuthorize("@ato.hasAuthority('mall:orderrefunds:edit')")
    public R updateById(@RequestBody OrderRefunds orderRefunds) {
        return R.ok(orderRefundsService.updateById(orderRefunds));
    }

    /**
     * 通过id删除退款详情
     * @param id
     * @return R
     */
	@ApiOperation(value = "通过id删除退款详情")
    @SysLog("删除退款详情")
    @DeleteMapping("/{id}")
    @PreAuthorize("@ato.hasAuthority('mall:orderrefunds:del')")
    public R removeById(@PathVariable String id) {
        return R.ok(orderRefundsService.removeById(id));
    }

	/**
	 * 操作退款
	 * @param orderRefunds 退款详情
	 * @return R
	 */
	@ApiOperation(value = "操作退款")
	@SysLog("操作退款")
	@PutMapping("/doOrderRefunds")
	@PreAuthorize("@ato.hasAuthority('mall:orderinfo:edit')")
	public R doOrderRefunds(@RequestBody OrderRefunds orderRefunds) {
		Boolean b = orderRefundsService.doOrderRefunds(orderRefunds);
		if(b && (OrderRefundsEnum.STATUS_11.getValue().equals(orderRefunds.getStatus()))
				|| OrderRefundsEnum.STATUS_211.getValue().equals(orderRefunds.getStatus())){
			String id = orderRefunds.getId();
			OrderRefunds orderRefunds2 = orderRefundsService.getById(id);
			if(orderRefunds2.getRefundAmount().compareTo(BigDecimal.ZERO) <= 0){
				//0元退款直接处理结果
				orderRefundsService.doOrderRefundsResult(orderRefunds2);
				return R.ok(b);
			}
			OrderItem orderItem = orderItemService.getById2(orderRefunds2.getOrderItemId());
			OrderInfo orderInfo = orderInfoService.getById(orderItem.getOrderId());
			//支付宝没有退款回调，所以在发起退款后延时查询
			if(MallConstants.ORDER_PAYMENT_TYPE_2.equals(orderInfo.getPaymentType())){
				ShopInfo shopInfo = shopInfoService.getById(orderInfo.getShopId());
				try {
					//延时12秒查询结果
					Thread.sleep(12 * 1000);
					Map<String, Object> params2 = new HashMap<>();
					params2.put("outTradeNo",orderInfo.getOrderNo());
					params2.put("outRequestNo",orderRefunds2.getId());
					AliBaseRequest aliBaseRequest2 = new AliBaseRequest();
					aliBaseRequest2.setAppAuthToken(shopInfo.getAliAuthToken());
					aliBaseRequest2.setParams(params2);
					R<AlipayTradeFastpayRefundQueryResponse> r2 = feignJooLunPayService.queryRefundOrder(aliBaseRequest2, SecurityConstants.FROM_IN);
					log.debug("查询退款（支付宝）data："+r2);
					if(r2.isOk()){
						AlipayTradeFastpayRefundQueryResponse alipayTradeFastpayRefundQueryResponse = r2.getData();
						if(PayConstants.ALI_RES_CODE_SUCCESS.equals(alipayTradeFastpayRefundQueryResponse.getCode())
								&& "REFUND_SUCCESS".equals(alipayTradeFastpayRefundQueryResponse.getRefundStatus())){
							orderRefundsService.doOrderRefundsResult(orderRefunds2);
						}else{
							log.error("支付宝退款延时查询退款处理出错：",alipayTradeFastpayRefundQueryResponse);
						}
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		return R.ok(b);
	}

	/**
	 * 退款回调（微信）
	 * @param xmlData
	 * @return
	 * @throws WxPayException
	 */
	@ApiOperation(value = "退款回调（微信）")
	@PostMapping("/notify-refunds")
	public String notifyRefunds(@RequestBody String xmlData) {
		log.info("退款回调:"+xmlData);
		WxPayOrderNotifyResult rs = WxPayOrderNotifyResult.fromXML(xmlData);
		PayConfig payConfig = feignJooLunPayService.getPayConfig(rs.getAppid(), SecurityConstants.FROM_IN).getData();
		TenantContextHolder.setTenantId(payConfig.getTenantId());//设置租户ID
		R<WxPayRefundNotifyResult> r = feignJooLunPayService.notifyRefundsWx(xmlData, SecurityConstants.FROM_IN);
		if(r.isOk()){
			WxPayRefundNotifyResult notifyResult = r.getData();
			OrderRefunds orderRefunds = orderRefundsService.getById(notifyResult.getReqInfo().getOutRefundNo());
			if(orderRefunds != null){
				orderRefundsService.doOrderRefundsResult(orderRefunds);
				return WxPayNotifyResponse.success("成功");
			}else{
				return WxPayNotifyResponse.fail("无此订单详情");
			}
		}else{
			return WxPayNotifyResponse.fail(r.getMsg());
		}
	}
}
